#include "line_arc_error.h"



ArcSegmentIntersection::ArcSegmentIntersection(){

    std::random_device rd;

    gen = std::mt19937(rd());

    dist = std::uniform_real_distribution<>(-1.0,1.0);

    angle_dist = std::uniform_real_distribution<>(0,2 * M_PI);
}

void ArcSegmentIntersection::GenerateRandomArc(){

    center = {dist(gen),dist(gen)};

    radius = fabs(dist(gen) * 10);

    start_angle = angle_dist(gen);

    end_angle = angle_dist(gen);

    if(start_angle > end_angle) std::swap(start_angle,end_angle);

    double mid_angle = (start_angle + end_angle) / 2.0;

    mid_point = {center.x + radius * cos(mid_angle),
                 center.y + radius * sin(mid_angle)};
}

Point ArcSegmentIntersection::GenerateRandomPoint(){

    return  {dist(gen) * 10,dist(gen) * 10};

}
Point ArcSegmentIntersection::ReflectPoint(const Point& p){

    double dx = mid_point.x - p.x;

    double dy = mid_point.y - p.y;

    return {mid_point.x + dx ,mid_point.y + dy};
}

std::vector<Point> ArcSegmentIntersection::intersect(const Point& p1,const Point& p2){

    std::vector<Point> intersections;

    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    double fx = p1.x - center.x;
    double fy = p1.y - center.y;


    double a = dx * dx + dy * dy;
    double b = 2 * (fx * dx + fy * dy);
    double c = (fx * fx + fy * fy) - radius * radius;

    double det = b * b - 4 * a * c;

    if (det < 0) {
        return intersections;
    }

    double t1 = (-b - sqrt(det)) / (2 * a);
    double t2 = (-b + sqrt(det)) / (2 * a);

    if (t1 >= 0 && t1 <= 1) {
        Point p = { p1.x + t1 * dx,p1.y + t1 * dy };
        if (IsOnArc(p))    intersections.push_back(p);
    }

    if (t2 >= 0 && t2 <= 1 && det > 0) {
        Point p = { p1.x + t2 * dx,p1.y + t2 * dy };
        if (IsOnArc(p))    intersections.push_back(p);
    }

    return intersections;
}
double ArcSegmentIntersection::CalculateError(const Point& intersection){
    return sqrt(pow(intersection.x- mid_point.x,2) + pow(intersection.y - mid_point.y,2));
}



bool ArcSegmentIntersection::IsOnArc(const Point&p){
    double angle = atan2(p.y - center.y,p.x - center.x);
    if(angle < 0) angle += 2 * M_PI;
    return angle >= start_angle && angle <= end_angle;
}



